package com.qrcode.scan.camera;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Created by leo
 * on 2020/3/13.
 */
public class CameraInterface {

    private Camera mCamera;
    private Camera.Parameters parameters;
    private Context context;
    private static CameraInterface mCameraInterface;
    private int cameraWith;//当前camera所占宽度
    private int cameraHeight;//当前camera所占高度

    private int rightWith;//预览和图片的最佳尺寸
    private int rightHeight;//预览和图片的最佳尺寸

    private int cameraId;//照相机

    private SurfaceHolder mSurfaceHolder;//预览窗口
    private boolean isInitParams = false;
    private int mDegree;
    private Handler handler=null;
    private boolean isTakePhoto=false;

    private CameraInterface(Context context) {
        this.context = context;
    }

    public static synchronized CameraInterface getInstance(Context context) {
        if (mCameraInterface == null) {
            mCameraInterface = new CameraInterface(context);
        }
        return mCameraInterface;
    }

    public void restartPreview() {
        mCamera.startPreview();
    }

    public Camera getmCamera() {
        return mCamera;
    }

    //1、创建相机,参数是否是前置摄像头
    public void doOpenCamera(boolean isFront, SurfaceView mSurfaceView) {
        try {
            if (isFront) {
                mCamera = Camera.open(1);
                cameraId = 1;
            } else {
                mCamera = Camera.open();
                cameraId = 0;
            }
            initParams(mSurfaceView);
            //getRightSize();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("如果未打开权限会走这", "相机权限未打开!");
        }
    }

    public void initParams(SurfaceView mSurfaceView) {
        if (mSurfaceView == null) {
            return;
        }

        mSurfaceHolder = mSurfaceView.getHolder();

        //获得相机参数
        parameters = mCamera.getParameters();
        parameters.setPictureFormat(PixelFormat.JPEG);
        mDegree = CameraPreviewUtils.displayOrientation(context, cameraId);
        int mPreviewWidth;
        int mPreviewHight;
        mCamera.setDisplayOrientation(mDegree);
        // 设置后无效，camera.setDisplayOrientation方法有效
        parameters.set("rotation", mDegree);
        Log.e("initParams", "degree:" + mDegree);
        DisplayMetrics dm = new DisplayMetrics();
        Display display = ((Activity) (context)).getWindowManager().getDefaultDisplay();
        display.getMetrics(dm);
        int mDisplayWidth = dm.widthPixels;
        int mDisplayHeight = dm.heightPixels;

        Point point = CameraPreviewUtils.getBestPreview(parameters,
                new Point(mDisplayWidth, mDisplayHeight));

        mPreviewWidth = point.x;
        mPreviewHight = point.y;
        // Preview 768,432


        Point pointSize = CameraPreviewUtils.doStartPreview(context, mSurfaceView, mCamera, parameters);
        if (pointSize != null) {
            mPreviewWidth = pointSize.x;
            mPreviewHight = pointSize.y;
        }


        try {
            parameters.setPreviewSize(mPreviewWidth, mPreviewHight);
           /* if (cameraId == 1) {
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            }*/
            //doReStopCamera();
            getRightSize();
            setParameters();
            //.setParameters(parameters);
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("doOpenCamera", "摄像头初始化有误1");
        }

        try {
            mCamera.stopPreview();
            mCamera.setPreviewDisplay(mSurfaceHolder);
            mCamera.startPreview();
            isTakePhoto=false;
            autoCamera();
        } catch (RuntimeException e) {
            e.printStackTrace();
            Log.e("doOpenCamera", "摄像头初始化有误2");
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("doOpenCamera", "摄像头初始化有误3");
        }
    }


    // 2、开始预览
    public void doStartPreview(SurfaceHolder surfaceHolder, int with, int height) {
        try {
            cameraWith = with;
            cameraHeight = height;
        } catch (Exception e) {
            e.printStackTrace();
        }
        /*if (mCamera != null) {
            try {
                cameraWith = with;
                cameraHeight = height;
                //mSurfaceHolder = surfaceHolder;
                //reStartCamera();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }*/
    }


    /**
     * 重置预览
     */
    public void reStartCamera() {
        try {
            if (mCamera == null) {
                //设置相机参数
                /*setParameters();
                //这里要注意系统默认的横屏的。我们要将其转换成竖屏，旋转90°
                mCamera.setDisplayOrientation(90);
                mCamera.setPreviewDisplay(mSurfaceHolder);
                mCamera.startPreview();*/
                //mCamera.stopPreview();
                /*mCamera.setDisplayOrientation(mDegree);
                mCamera.startPreview();*/
               /* mCamera.setPreviewDisplay(mSurfaceHolder);
                mCamera.stopPreview();
                mCamera.startPreview();*/
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //3、关闭相机
    public void doStopCamera() {
        if (mCamera != null) {
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.cancelAutoFocus();
            mCamera.release();
            mCamera = null;
            destroy();
        }
    }


    public void setParameters() {
        //parameters.setPreviewSize(rightWith, rightHeight);
        parameters.setPictureSize(rightWith, rightHeight);
        //设置jpg格式
        parameters.setPictureFormat(ImageFormat.JPEG);
        //设置自动聚焦
        List<String> focusModes = parameters.getSupportedFocusModes();
//        Camera.Parameters.FOCUS_MODE_AUTO
        if (focusModes.contains("continuous-video")) {
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        }

        //设备支持闪光灯，且为后置摄像头才设置闪光模式
        if (isSupportFlash() && cameraId == 0) {
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
        }
        mCamera.setParameters(parameters);
    }

    //切换闪光灯模式
    public void switchFlash(int flashMode) {
        if (parameters == null || mCamera == null) {
            return;
        }
        if (!isSupportFlash() || cameraId == 1) {
            //设备不支持闪光灯模式，或者是前置摄像头
            return;
        }
        if (flashMode % 3 == 0) {
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
        } else if (flashMode % 3 == 1) {
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
        } else if (flashMode % 3 == 2) {
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
        }
        mCamera.setParameters(parameters);
        mCamera.startPreview();
    }


    /**
     * 照相
     */
    public void takePicture(final OnCaptureData callback) {
        if (mCamera == null) {
            return;
        }
        isTakePhoto=true;
        mCamera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                boolean success = false;
                if (data != null && data.length > 0) {
                    success = true;
                }
                //点击拍照，停止预览
                mCamera.stopPreview();
                //这个是图片截图用的。
                String path = savePicture(data);
//                Bitmap endBit = Bitmap.createScaledBitmap(savePicture(data), 1080, 1794, true);
                callback.onCapture(success, path);
            }
        });
    }


    //这是获取预览图的接口。什么意思呢？
    //比如上面的takePicture,即使不做任何处理，点击拍照也会停留顿一下。
    //说个小需求，如果加上相机人脸识别，当相机里出现人脸的画，需要取几张人脸的图，用拍照就不好实现了。得用下面的实现。
    public void takeOneShotPreview() {
        mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {

            }
        });
    }


    private String savePicture(byte[] data) {

        File imgFileDir = getImageDir();
        if (!imgFileDir.exists() && !imgFileDir.mkdirs()) {
            return null;
        }
        //文件路径路径
        String imgFilePath = context.getFilesDir().getAbsolutePath().toString() + "/" + TimeUtils.getDateToStringLeo(System.currentTimeMillis() + "") + "_atmancarm.jpg";
        Bitmap b = BitmapFactory.decodeByteArray(data, 0, data.length);

        Bitmap rotatedBitmap = null;
        if(b.getHeight()>b.getWidth()){
            if (null != b) {
                if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
                    rotatedBitmap=b;
                } else if (cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    rotatedBitmap = ImageUtil.getRotateBitmap_front(b, -180.0f);
                }
            }
        }else {
            if (null != b) {
                if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
                    rotatedBitmap = ImageUtil.getRotateBitmap(b, 90.0f);
                } else if (cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    rotatedBitmap = ImageUtil.getRotateBitmap_front(b, -90.0f);
                }
            }
        }

       /* int truePicHeight;
        //注意rightWith 和rightHeight原手机横屏的尺寸。也就是说rightHeight是我们真实的预览和图片尺寸的宽度
        truePicHeight = rightHeight * cameraHeight / cameraWith;
        if (truePicHeight > rightWith) {
            truePicHeight = rightWith;
        }

        rotatedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, rightHeight, truePicHeight, true);*/
        //注意rightWith 和rightHeight原手机横屏的尺寸。也就是说rightHeight是我们真实的预览和图片尺寸的宽度
        int truePicWith=cameraWith;
        int truePicHeight = cameraWith*rotatedBitmap.getHeight() / rotatedBitmap.getWidth();
        Log.e("宽","PWith:"+cameraWith);
        Log.e("高","PHeight:"+truePicHeight);
        rotatedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, truePicWith, truePicHeight, true);


        File imgFile = new File(imgFilePath);
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        try {
            fos = new FileOutputStream(imgFile);
            bos = new BufferedOutputStream(fos);
            rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        } catch (Exception error) {
            return null;
        } finally {
            try {
                if (fos != null) {
                    fos.flush();
                    fos.close();
                }
                if (bos != null) {
                    bos.flush();
                    bos.close();
                }
            } catch (IOException e) {
            }

        }

        return imgFilePath;
    }


    private File getImageDir() {
        String path =
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath();
        File file = new File(path);
        if (!file.exists()) {
            file.mkdir();
        }
        return file;
    }


    private CameraSizeComparator sizeComparator = new CameraSizeComparator();

    public void getRightSize() {
        if (rightWith != 0 && rightHeight != 0) {
            return;
        }
        //获取camera api 当前设备支持的预览尺寸
        List<Camera.Size> listPreview = parameters.getSupportedPreviewSizes();
        Collections.sort(listPreview, sizeComparator);
        ArrayList<String> flagComparator = new ArrayList<>();

        for (int i = 0; i < listPreview.size(); i++) {
            Camera.Size size = listPreview.get(i);
            int flag = size.width + size.height;
            flagComparator.add(flag + "");
        }
        //获取camera api 当前设备支持的相机尺寸
        List<Camera.Size> listPicture = parameters.getSupportedPictureSizes();
        Collections.sort(listPicture, sizeComparator);

        for (int i = 0; i < listPicture.size(); i++) {
            Camera.Size size = listPicture.get(i);
            int flag = size.width + size.height;
            if (flagComparator.contains(flag + "")) {
                rightWith = size.width;
                rightHeight = size.height;
                return;
            }
        }
    }


    public int getRightWith() {
        return rightWith;
    }

    public int getRightHeight() {
        return rightHeight;
    }

    public int getCameraId() {
        return cameraId;
    }


    //降序的排序规则
    public class CameraSizeComparator implements Comparator<Camera.Size> {
        public int compare(Camera.Size lhs, Camera.Size rhs) {
            if (lhs.width == rhs.width) {
                return 0;
            } else if (lhs.width > rhs.width) {
                return -1;
            } else {
                return 1;
            }
        }
    }

    /**
     * 判断设备是否支持闪光灯
     */
    private boolean isSupportFlash() {
        if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
            return false;
        } else {
            return true;
        }
    }

    @SuppressLint("HandlerLeak")
    private void autoCamera(){
        if(handler==null){
            handler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what){
                        case 0x01:
                            try {
                                if(mCamera!=null&&!isTakePhoto) {
                                    mCamera.autoFocus(new Camera.AutoFocusCallback() {
                                        @Override
                                        public void onAutoFocus(boolean success, Camera camera) {
                                            //Log.e("自动对焦","autoCamera--onAutoFocus:"+success);
                                        }
                                    });
                                    //Log.e("自动对焦","autoCamera");
                                    handler.sendEmptyMessageDelayed(0x01, 1 * 500);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            break;
                        default:
                            break;
                    }
                }};
            handler.sendEmptyMessageDelayed(0x01, 1 * 500);
        }else{
            handler.sendEmptyMessageDelayed(0x01, 1 * 500);
        }
    }


    /**
     * 这块是关于视频录制的
     */
    MediaRecorder mMediaRecorder;
    String videoPath;

    public boolean prepareVideoRecorder(SurfaceHolder surfaceHolder) {
        videoPath = context.getFilesDir().getAbsolutePath().toString() + "/" + TimeUtils.getDateToStringLeo(System.currentTimeMillis() + "") + "_atmancarm.mp4";

        mMediaRecorder = new MediaRecorder();

        // Step 1: Unlock and set camera to MediaRecorder
        mCamera.unlock();
        mMediaRecorder.setCamera(mCamera);

        // Step 2: Set sources
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

        // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
        mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

        // Step 4: Set output file
        mMediaRecorder.setOutputFile(videoPath);

        // Step 5: Set the preview output
        mMediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
        if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            mMediaRecorder.setOrientationHint(90);
        } else if (cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            mMediaRecorder.setOrientationHint(270);
        }


        // Step 6: Prepare configured MediaRecorder
        try {
            mMediaRecorder.prepare();
        } catch (IllegalStateException e) {
            releaseMediaRecorder();
            return false;
        } catch (IOException e) {
            releaseMediaRecorder();
            return false;
        }
        return true;
    }


    public void startRecord() {
        mMediaRecorder.start();
    }

    public String stopRecod() {
        mMediaRecorder.stop();
        return videoPath;
    }


    public void releaseMediaRecorder() {
        if (mMediaRecorder != null) {
            mMediaRecorder.reset();   // clear recorder configuration
            mMediaRecorder.release(); // release the recorder object
            mMediaRecorder = null;
            mCamera.lock();           // lock camera for later use
        }
    }

    public void destroy(){
        try {
            handler=null;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
